package controller

import (
	"GoTime/models"
	"GoTime/response"
	. "GoTime/utils"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strconv"

	"strings"
	"time"

	"github.com/mozillazg/request"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"xorm.io/builder"
)

func GetCarList(c *gin.Context) {
	var (
		carList  []response.CarListResponse
		err      error
		page     int
		pageSize int
		offset   int
		count    int64
	)
	// 检查请求中是否包含驾校ID参数
	if c.Query("school_id") == "" {
		// 如果驾校ID参数为空，返回错误信息
		c.JSON(http.StatusBadRequest, gin.H{"code": 201, "msg": "请选择驾校"})
		return
	}
	// 创建一个新的查询条件构建器
	filter := builder.NewCond()
	// 添加驾校ID的查询条件
	filter = filter.And(builder.Eq{"c.school_id": c.Query("school_id")})
	if plateNumber := c.Query("plate_number"); plateNumber != "" {
		filter = filter.And(builder.Like{"c.plate_number", plateNumber})
	}
	if trainingType := c.Query("training_car_type"); trainingType != "" {
		filter = filter.And(builder.Eq{"c.training_type": trainingType})
	}
	if carSerial := c.Query("car_serial"); carSerial != "" {
		filter = filter.And(builder.Like{"c.car_serial", carSerial})
	}
	if status := c.Query("status"); status != "" {
		filter = filter.And(builder.Eq{"c.status": status})
	}
	page = cast.ToInt(c.DefaultQuery("page", "0"))
	pageSize = cast.ToInt(c.DefaultQuery("pageSize", "10"))
	offset = (page - 1) * pageSize
	count, carList, err = new(models.Car).GetCarList(filter, pageSize, offset)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "获取车辆列表失败", "data": err})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取车辆列表成功", "data": gin.H{"count": count, "carList": carList}})
	return
}

func AddCar(c *gin.Context) {
	var (
		err    error
		url    string
		retMap map[string]interface{}
	)
	// 创建一个新的Car模型实例
	car := new(models.Car)
	portrait := new(models.CarPortrait)

	// 绑定请求参数到Car模型实例，如果绑定失败，返回错误信息
	if err := c.ShouldBind(car); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return
	}
	if err := c.ShouldBind(portrait); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "参数错误"})
		return
	}
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(c.PostForm("school_id")))
	if err != nil || !ok {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}
	car.InstitutionCode = GetInstitutionCode(car.PlateNumber)
	if car.PlateNumber != "" && car.HasPlateNumber(1) {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "车牌号:" + car.PlateNumber + " 已存在"})
		return
	}
	// 获取数据库引擎实例
	var engine = models.Engine
	// 创建一个新的数据库会话
	var session = engine.NewSession()
	// 确保在函数结束时关闭会话
	defer session.Close()

	// 开始一个数据库事务
	if err := session.Begin(); err != nil {
		// 如果事务开始失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "事务开始失败"})
		return
	}
	if c.PostForm("purchase_date") == "" {
		car.PurchaseDate = ""
	} else {
		car.PurchaseDate = c.PostForm("purchase_date")
	}
	if c.PostForm("on_service_date") == "" {
		car.OnServiceDate = time.Now()
	} else {
		car.OnServiceDate, _ = time.Parse("2006-01-02", c.PostForm("on_service_date"))
	}
	if c.PostForm("out_service_date") == "" {
		car.OnServiceDate = time.Now()
	} else {
		car.OutServiceDate, _ = time.Parse("2006-01-02", c.PostForm("out_service_date"))
	}
	if c.PostForm("energytype") != "" {
		car.EnergyType = c.PostForm("energytype")
	}
	car.Isused = "1"
	car.HisplateNumber = ""
	car.ApprovalStatus = "0"
	car.Remark = ""
	if _, err = session.Insert(car); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	portrait.CarId = car.Id
	portrait.AddTime = time.Now()
	if _, err = session.Insert(portrait); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	if c.PostForm("retain") == "1" {
		err = session.Commit()
		if err != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "添加车辆成功"})
		return
	}

	data := map[string]interface{}{
		"carnum":      car.InstitutionCode,                          //教练车编号
		"inscode":     school.InstitutionCode,                       //培训机构编号
		"licnum":      car.PlateNumber,                              //车辆牌号
		"platecolor":  car.Color,                                    //车牌颜色
		"photo":       portrait.InstitutionCode,                     //照片文件ID
		"manufacture": car.Manufacture,                              //生产厂家
		"brand":       car.Brand,                                    //车辆品牌
		"model":       car.Model,                                    //车辆型号
		"perdritype":  car.TrainingType,                             //培训车型
		"franum":      car.Framenum,                                 //车架号
		"engnum":      car.Engnum,                                   //发动机号
		"regsdate":    strings.Replace(car.Regsdate, "-", "", -1),   //注册日期
		"scrapdate":   strings.Replace(car.Scrapdate, "-", "", -1),  //报废日期
		"verifydate":  strings.Replace(car.Verifydate, "-", "", -1), //审验日期
		"techlevel":   car.Techlevel,                                //技术等级
	}
	if data["photo"], err = FileId(portrait.ImageUrl, "vehimg", 2, school.Province, school.City); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	if car.EnergyType != "" {
		data["energytype"] = car.EnergyType //能源类型
	}
	if car.PurchaseDate != "" {
		data["buydate"] = strings.Replace(car.PurchaseDate, "-", "", -1)
	}
	if url, err = GetSignURL("trainingcar", data, 2, school.Province, school.City); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	var api_log models.ApiLog
	param, err := json.Marshal(data)
	api_log.Url = url
	api_log.Param = string(param)
	api_log.Method = "POST"
	api_log.UserId, _ = strconv.Atoi(c.PostForm("user_id"))
	api_log.Time = time.Now()
	if retMap, err = APIReq(url, data, "POST"); err != nil {
		result, _ := json.Marshal(retMap)
		api_log.Result = string(result)
		api_log.Add()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	result, _ := json.Marshal(retMap)
	api_log.Result = string(result)
	api_log.Add()
	fmt.Println(retMap)
	errorcode, _ := cast.ToFloat64E(retMap["errorcode"])
	if errorcode != 0 && !strings.Contains(retMap["message"].(string), "已经备案") {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": errorcode, "msg": retMap["message"]})
		return
	}

	_, err = session.Exec("update dts_car set record_status=?,institution_code=? where id = ?", "1", car.InstitutionCode, car.Id)
	if err != nil {
		session.Rollback()
		return
	}
	err = session.Commit()
	if err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": errorcode, "msg": err})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "添加车辆成功"})
	return
}

func EditCar(c *gin.Context) {
	var (
		car         *models.Car
		err         error
		carPortrait *models.CarPortrait
		url         string
		retMap      map[string]interface{}
		reqType     int64
	)
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(c.PostForm("school_id")))
	if err != nil || !ok {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "驾校不存在"})
		return
	}
	// 通过教练ID获取教练信息
	car, err = new(models.Car).GetOneCarById(c.PostForm("car_id"))
	if err != nil || car.Id <= 0 {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "教练车不存在"})
		return
	}
	prePlateNumber := car.PlateNumber

	if car.PlateNumber != prePlateNumber {
		if car.HasPlateNumber(2) {
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "该车牌号码已经存在"})
			return
		}
	}
	// 从请求参数中获取数据并绑定到coach结构体
	if err := c.ShouldBind(car); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	if car.InstitutionCode == "" {
		car.InstitutionCode = GetInstitutionCode(car.PlateNumber)
	}
	if c.PostForm("energytype") != "" {
		car.EnergyType = c.PostForm("energytype")
	}
	car.PurchaseDate = c.PostForm("purchase_date")
	car.ApprovalStatus = "0"
	if car.InstitutionCode == "" {
		car.InstitutionCode = GetInstitutionCode(car.PlateNumber)
	}
	// 获取数据库引擎实例
	var engine = models.Engine
	// 创建一个新的数据库会话
	var session = engine.NewSession()
	// 确保在函数结束时关闭会话
	defer session.Close()
	// 开始一个数据库事务
	if err := session.Begin(); err != nil {
		// 如果事务开始失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "事务开始失败", "data": err.Error()})
		return
	}
	// 更新数据库中的图片信息1.先搜索有这个图片吗，没有就添加 。2.有就进行更换
	if carPortrait, err = new(models.CarPortrait).GetPortraitByCarId(c.PostForm("car_id")); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err})
		return
	}
	if carPortrait.Id == 0 {
		//添加
		//插入车图片表中
		carPortrait.CarId = car.Id
		carPortrait.InstitutionCode = c.PostForm("portrait_code")
		carPortrait.ImageUrl = c.PostForm("image_url")
		carPortrait.DrivingLicenseA = c.PostForm("driving_license_a")
		carPortrait.DrivingLicenseB = c.PostForm("driving_license_b")
		if _, err := session.Insert(carPortrait); err != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆照片失败"})
			return
		}
	} else {
		//修改
		carPortrait.CarId = car.Id
		carPortrait.InstitutionCode = c.PostForm("portrait_code")
		carPortrait.ImageUrl = c.PostForm("image_url")
		carPortrait.DrivingLicenseA = c.PostForm("driving_license_a")
		carPortrait.DrivingLicenseB = c.PostForm("driving_license_b")
		if _, err2 := session.ID(carPortrait.Id).Cols("car_id", "institution_code", "image_url", "driving_license_a", "driving_license_b").Update(carPortrait); err2 != nil {
			session.Rollback()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆照片失败"})
			return
		}
	}
	// 更新数据库中的车辆信息
	if _, err := session.ID(car.Id).Cols("institution_code", "regsdate", "scrapdate", "verifydate", "techlevel", "energy_type", "framenum", "plate_number", "manufacture", "brand", "model", "color", "training_type", "purchase_date", "status", "record_status", "engnum").Update(car); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "更新车辆信息失败"})
		return
	}
	// 备案车辆信息
	data := map[string]interface{}{
		"carnum":      car.InstitutionCode,                          //教练车编号
		"inscode":     school.InstitutionCode,                       //培训机构编号
		"licnum":      car.PlateNumber,                              //车辆牌号
		"platecolor":  car.Color,                                    //车牌颜色
		"photo":       carPortrait.InstitutionCode,                  //照片文件ID
		"manufacture": car.Manufacture,                              //生产厂家
		"brand":       car.Brand,                                    //车辆品牌
		"model":       car.Model,                                    //车辆型号
		"perdritype":  car.TrainingType,                             //培训车型
		"franum":      car.Framenum,                                 //车架号
		"engnum":      car.Engnum,                                   //发动机号
		"regsdate":    strings.Replace(car.Regsdate, "-", "", -1),   //注册日期
		"scrapdate":   strings.Replace(car.Scrapdate, "-", "", -1),  //报废日期
		"verifydate":  strings.Replace(car.Verifydate, "-", "", -1), //审验日期
		"techlevel":   car.Techlevel,                                //技术等级
	}
	if car.EnergyType != "" {
		data["energytype"] = car.EnergyType //能源类型
	}
	if car.PurchaseDate != "" {
		data["buydate"] = strings.Replace(car.PurchaseDate, "-", "", -1)
	}
	if carPortrait.ImageUrl == "" {
		c.JSON(http.StatusOK, gin.H{"code": 202, "msg": "车辆照片未上传"})
		return
	}
	reqType = 2
	//data["photo"], err = FileId(carPortrait.ImageUrl, "vehimg", reqType, school.Province, school.City)
	log.Print(err)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 202, "msg": "图片文件过大,照片未上传,请修改图片文件后重新上传"})
		return
	}
	if url, err = GetSignURL("trainingcar", data, reqType, school.Province, school.City); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	var api_log models.ApiLog
	param, err := json.Marshal(data)
	api_log.Url = url
	api_log.Param = string(param)
	api_log.Method = "POST"
	api_log.UserId, _ = strconv.Atoi(c.PostForm("user_id"))
	api_log.Time = time.Now()
	if retMap, err = APIReq(url, data, "POST"); err != nil {
		result, _ := json.Marshal(retMap)
		api_log.Result = string(result)
		api_log.Add()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "添加车辆失败"})
		return
	}
	result, _ := json.Marshal(retMap)
	api_log.Result = string(result)
	api_log.Add()
	fmt.Println(retMap)
	errorcode, _ := cast.ToFloat64E(retMap["errorcode"])
	if errorcode != 0 && !strings.Contains(retMap["message"].(string), "已经备案") {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": retMap["message"]})
		return
	}
	car.RecordStatus = "1"
	car.ApprovalStatus = "0"
	if _, err := session.ID(car.Id).Cols("record_status", "approval_status").Update(car); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "更新车辆信息失败"})
		return
	}
	session.Commit()
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "更新成功"})
	return
}

func DeleteCar(c *gin.Context) {
	var (
		carId       string
		schoolId    string
		car         *models.Car
		terminalCar models.TerminalCar
		reqType     int64
		url         string
		retMap      map[string]interface{}
	)
	// 获取请求中的场地ID参数
	if carId = c.Query("car_id"); carId == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "缺少车辆ID"})
		return
	}

	// 获取请求中的驾校ID参数
	if schoolId = c.Query("school_id"); schoolId == "" {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "缺少驾校ID"})
		return
	}

	// 查询指定驾校ID的驾校信息
	ok, school, err := new(models.School).GetSchoolById(cast.ToInt(schoolId))
	if err != nil || !ok {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询驾校信息失败"})
		return
	}

	// 获取数据库引擎实例
	var engine = models.Engine

	// 创建一个新的数据库会话
	var session = engine.NewSession()

	// 确保在函数结束时关闭会话
	defer session.Close()

	// 开始一个数据库事务
	if err := session.Begin(); err != nil {
		// 如果事务开始失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "事务开始失败", "data": err.Error()})
		return
	}
	if car, err = new(models.Car).GetOneCarById(cast.ToInt(carId)); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "查询车辆信息失败"})
		return
	}
	// 查询是否已绑定设备
	if row, _ := session.Table("dts_terminal_car").Where("car_id = ?", carId).Get(terminalCar); row {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "当前已绑定，先解绑后删除"})
		return
	}
	if url, err = GetSignURL("trainingCar-"+car.InstitutionCode, nil, reqType, school.Province, school.City); err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "删除车辆失败"})
		return
	}
	apiMethod := "DELETE"
	isWuHan := school.City == "420100"
	shanDong := school.Province == "370000"
	isAnHui := school.Province == "340000"
	if isWuHan || shanDong || isAnHui {
		apiMethod = "GET"
	}
	var apiLog models.ApiLog
	apiLog.Url = url
	apiLog.Param = ""
	apiLog.Method = "POST"
	apiLog.UserId = school.UserId
	apiLog.Time = time.Now()
	if school.Province == "370000" || school.Province == "340000" || school.Province == "420000" {
		client := new(http.Client)
		req := request.NewRequest(client)
		resp, err := req.Get(url)
		defer resp.Body.Close()
		var (
			body []byte
		)
		if body, err = io.ReadAll(resp.Response.Body); err != nil {
			log.Println(err)
		}
		if err = json.Unmarshal(body, &retMap); err != nil {
			log.Println(err)
		}
	} else {
		if retMap, err = APIReq(url, nil, apiMethod); err != nil {
			result, _ := json.Marshal(retMap)
			apiLog.Result = string(result)
			apiLog.Add()
			c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "删除车辆失败"})
			return
		}
	}
	result, _ := json.Marshal(retMap)
	apiLog.Result = string(result)
	apiLog.Add()
	fmt.Println(retMap)
	car.RecordStatus = "0"
	car.ApprovalStatus = "0"
	car.Isused = "0"
	car.HisplateNumber = car.PlateNumber
	car.Remark = car.InstitutionCode
	car.InstitutionCode = ""
	car.PlateNumber = fmt.Sprint(time.Now().UnixNano() / 1e6)
	if _, err := session.ID(car.Id).Cols("record_status", "approval_status", "isused", "hisplate_number", "remark", "institution", "plate_number").Update(car); err != nil {
		session.Rollback()
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": "删除车辆失败"})
		return
	}
	session.Commit()
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "删除成功"})
	return
}
